﻿using Prism.Mvvm;

namespace IceMan.Domain
{
    public class Strawberry : BaseMaterialType
    {
        public static Strawberry Default = new Strawberry();

        private Strawberry()
        {

        }
        public override string Name => "草莓";
    }

    public class IceCream : BaseMaterialType
    {
        private IceCream()
        {

        }
        public static IceCream Default = new IceCream();
        public override string Name => "冰激凌";
    }

    public class Chocolates : BaseMaterialType
    {
        private Chocolates()
        {

        }
        public static Chocolates Default = new Chocolates();
        public override string Name => "巧克力";
    }

    public abstract class BaseMaterialType : BindableBase, IMaterialType
    {
        protected BaseMaterialType()
        {

        }

        private object _countLock = new object();
        public abstract string Name { get; }



        private int remainCount;
        public int RemainCount
        {
            get { return remainCount; }
            private set { SetProperty(ref remainCount, value); }
        }

        /// <summary>
        /// 数量减少1
        /// </summary>
        /// <exception cref="InvalidOperationException"></exception>
        public void ReduceCount()
        {
            lock (_countLock)
            {
                if (RemainCount <= 0)
                {
                    throw new InvalidOperationException("数量小于0时，无法继续减少数量");
                }
                RemainCount--;
            }
        }

        /// <summary>
        /// 重置数量为指定值
        /// </summary>
        /// <param name="newCount"></param>
        public void ResetCount(int newCount)
        {
            RemainCount = newCount;
        }
    }
    public interface IMaterialType
    {
        /// <summary>
        /// 材料名称
        /// </summary>
        string Name { get; }

        /// <summary>
        /// 材料剩余数量
        /// </summary>
        int RemainCount { get; }

        void ReduceCount();

        void ResetCount(int newCount);
    }
    public class StateContainer : BindableBase
    {
        List<IMaterialType> states;

        /// <summary>
        /// 当前状态的索引号
        /// </summary>
        int stateIndex = -1;
        public StateContainer(List<IMaterialType> states, int changeStateInterval, WorkType workType)
        {
            this.states = states;
            this.ChangeStateInterval = changeStateInterval;
            WorkType = workType;
        }

        public CancellationTokenSource CancellationTokenSource { get; set; } = new CancellationTokenSource();
        public WorkType WorkType { get; }
        /// <summary>
        /// 切换状态的间隔时间
        /// </summary>
        public double ChangeStateInterval { get; set; }

        /// <summary>
        /// 切换状态到指定值。
        /// 在软件启动时，会检测上次的执行状态，
        /// 如果上次有未完成的任务，则使用此方法，恢复到上次未完成的状态，然后继续开启后续状态切换
        /// </summary>
        public void ChangeStateTo(string matName)
        {
            // 上次已完成的状态索引
            var lastFinishedIndex = states.FindIndex(x => x.Name == matName);
            if (lastFinishedIndex == -1)
            {
                throw new ArgumentException($"材料名称为{matName}的材料不存在");
            }
            else
            {
                // 新状态是上次已完成的任务
                stateIndex = lastFinishedIndex;
            }
        }

        /// <summary>
        /// 恢复为初始空闲状态
        /// </summary>
        public void ResetInitState()
        {
            stateIndex = -1;

            IsRunning = false;

            CancellationTokenSource.Cancel();

            CancellationTokenSource.Dispose();

            CancellationTokenSource = new CancellationTokenSource();
        }

        /// <summary>
        ///  是否处于初始空闲状态
        /// </summary>
        public bool IsInitState => stateIndex == -1;

        public string GetStartButtonText()
        {
            if (WorkType== WorkType.ReplaceMaterial)
            {
                if (IsInitState)
                {
                    return "开始更换材料";
                }
                else
                {
                    return "继续更换材料";
                }
            }
            else
            {
                if (IsInitState)
                {
                    return "开始制作";
                }
                else
                {
                    return "继续制作";
                }
            }
            
        }

        /// <summary>
        /// 当前状态正在进行中
        /// </summary>
        private bool isRunning;
        public bool IsRunning
        {
            get { return isRunning; }
            private set { SetProperty(ref isRunning, value); }
        }
        /// <summary>
        /// 切换到下一个状态，如果切换状态成功，
        /// 返回false，切换状态失败，说明已经是最后一个状体
        /// 此时返回true
        /// </summary>
        /// <returns></returns>
        public bool NextState()
        {
            // 到了最后一个状态
            if (stateIndex == states.Count - 1)
            {
                stateIndex = -1;
                IsRunning = false;
                return false;
            }
            else
            {
                IsRunning = true;
                stateIndex++;
                return true;
            }
        }

        public Task DoWork()
        {
            return Task.Delay((int)ChangeStateInterval * 1000);
        }

        public IMaterialType CurrentState => states[stateIndex];

        /// <summary>
        /// 前一个状态
        /// </summary>
        public IMaterialType? PreviousState => stateIndex == 0 ? null : states[stateIndex - 1];

        public string GetStateInfo()
        {
            if (stateIndex == -1)
            {
                return "空闲中";
            }

           
            if (IsRunning)
            {
                if (PreviousState != null)
                {
                    return $"{PreviousState.Name}已完成,正在添加{CurrentState.Name}";
                }
                else
                {
                    return $"正在添加{CurrentState.Name}";
                }
            }
            else
            {
                // 非运行时，说明要显示上次停止时的状态。
                return $"上次已完成{CurrentState.Name}添加,后续将添加{states[stateIndex + 1].Name}";
            }
            

        }
    }
}